Skip to content

Conversation

@gronxb
Copy link
Collaborator

@gronxb gronxb commented Dec 1, 2025

Context

The existing createFullyTransformStep only works in a zod environment because of the emoji regex. By changing it to a step that transforms the emoji regex instead, it will no longer be limited to zod and will support both zod and valibot.

Test Plan

yarn dev --experimental-mode

and use valibot and zod

Test Page

import { createRoute, Stack } from '@granite-js/react-native';
import { StyleSheet, Text, View } from 'react-native';
import * as z from 'zod';
import * as v from 'valibot';

export const Route = createRoute('/', {
  component: Page,
});

function Page() {
  // zod: only accept a nonempty string
  const zodSchema = z.object({
    name: z.string().min(1, 'Please enter a name!'),
  });

  // Test zod invalid
  const zodInvalid = zodSchema.safeParse({ name: '' });
  // Test zod valid
  const zodValid = zodSchema.safeParse({ name: 'John Doe' });

  const valibotInvalid = v.safeParse(
    v.object({
      name: v.pipe(v.string(), v.minLength(1, 'Please enter a name!')),
    }),
    { name: '' }
  );
  const valibotValid = v.safeParse(
    v.object({
      name: v.pipe(v.string(), v.minLength(1, 'Please enter a name!')),
    }),
    { name: 'John Doe' }
  );

  return (
    <Stack.Vertical style={styles.container} gutter={16}>
      <Text style={styles.title}>zod & valibot Validation Demo</Text>
      <Text style={styles.subtitle}>All tests run automatically</Text>

      <Text style={styles.schemaSectionTitle}>zod schema</Text>
      <View style={styles.schemaBox}>
        <Text style={styles.schemaCode}>{`z.object({\n  name: z.string().min(1, 'Please enter a name!'),\n})`}</Text>
      </View>

      <Text style={styles.sectionTitle}>zod results</Text>
      <Text style={zodInvalid.success ? styles.resultSuccess : styles.resultError}>
        zod (empty): {zodInvalid.success ? 'pass' : `fail - ${zodInvalid.error.issues[0]?.message ?? 'error'}`}
      </Text>
      <Text style={zodValid.success ? styles.resultSuccess : styles.resultError}>
        zod ('John Doe'): {zodValid.success ? 'pass' : `fail - ${zodValid.error.issues[0]?.message ?? 'error'}`}
      </Text>

      <Text style={styles.schemaSectionTitle}>valibot schema</Text>
      <View style={styles.schemaBox}>
        <Text style={styles.schemaCode}>
          {`v.object({\n  name: v.pipe(v.string(), v.minLength(1, 'Please enter a name!')),\n})`}
        </Text>
      </View>

      <Text style={styles.sectionTitle}>valibot results</Text>
      <Text style={valibotInvalid.success ? styles.resultSuccess : styles.resultError}>
        valibot (empty): {valibotInvalid.success ? 'pass' : `fail - ${valibotInvalid.issues[0]?.message ?? 'error'}`}
      </Text>
      <Text style={valibotValid.success ? styles.resultSuccess : styles.resultError}>
        valibot ('John Doe'): {valibotValid.success ? 'pass' : `fail - ${valibotValid.issues[0]?.message ?? 'error'}`}
      </Text>
    </Stack.Vertical>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
    backgroundColor: 'white',
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 28,
    fontWeight: 'bold',
    color: '#1A202C',
    textAlign: 'center',
    marginBottom: 8,
  },
  subtitle: {
    fontSize: 16,
    color: '#718096',
    marginBottom: 24,
    textAlign: 'center',
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: '600',
    marginTop: 20,
    marginBottom: 4,
    color: '#353F53',
  },
  schemaSectionTitle: {
    fontSize: 16,
    fontWeight: '500',
    color: '#718096',
    marginTop: 18,
    marginBottom: 2,
    alignSelf: 'flex-start',
  },
  schemaBox: {
    backgroundColor: '#f5f5f5',
    borderRadius: 8,
    padding: 10,
    marginBottom: 8,
    alignSelf: 'stretch',
  },
  schemaCode: {
    fontFamily: 'monospace',
    color: '#353F53',
    fontSize: 13,
  },
  resultSuccess: {
    color: '#3182ce',
    marginTop: 4,
    fontSize: 16,
  },
  resultError: {
    color: '#E53E3E',
    marginTop: 4,
    fontSize: 16,
  },
});
image image

@changeset-bot
Copy link

changeset-bot bot commented Dec 1, 2025

🦋 Changeset detected

Latest commit: 0e9b4a4

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 21 packages
Name Type
@granite-js/react-native Patch
@granite-js/plugin-core Patch
@granite-js/native Patch
@granite-js/mpack Patch
@granite-js/cli Patch
@granite-js/plugin-env Patch
@granite-js/plugin-hermes Patch
@granite-js/plugin-micro-frontend Patch
@granite-js/plugin-router Patch
@granite-js/plugin-sentry Patch
@granite-js/forge-cli Patch
@granite-js/image Patch
@granite-js/jest Patch
@granite-js/lottie Patch
@granite-js/style-utils Patch
babel-preset-granite Patch
create-granite-app Patch
@granite-js/devtools-frontend Patch
@granite-js/utils Patch
@granite-js/deployment-manager Patch
@granite-js/pulumi-aws Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Dec 1, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
granite-docs Ready Ready Preview Comment Dec 1, 2025 2:41pm

Comment on lines +8 to +10
validateParams: v.object({
name: v.string(),
}),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

supports valibot and zod

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants